home *** CD-ROM | disk | FTP | other *** search
- /*
- DEONotificationCenter.m created by enoyau on Fri 13-Jan-1995
-
- You may freely copy, distribute, and reuse the code in this example.
- NeXT disclaims any warranty of any kind, expressed or implied, as to its
- fitness for any particular use.
- */
-
- #import "DEONotificationCenter.h"
- #import "DEONotification.h"
- #import "DEOServerMonitor.h"
- #import <foundation/NSException.h>
-
- #import <libc.h>
-
- NSString *DEOUpdate = @"DEOUpdate";
- NSString *DEOInsert = @"DEOInsert";
- NSString *DEODelete = @"DEODelete";
-
- @interface DEONotificationCenter(Communication) <DEOClient>
- - (void)registerAgain:(NSNotification *)note;
- @end
-
- // Holder object to allow the server to retain the proxy to
- // a DEONotificationCenter without retaining the center itself.
- // See comment in initWithDatabaseChannel:entity:
- @interface DEONotificationCenterHolder : NSObject <DEOClient>
- {
- DEONotificationCenter *center;
- }
- - initWithNonRetainedObject:(DEONotificationCenter *)aCenter;
- @end
-
-
- @implementation DEONotificationCenter
-
- static NSString *localHostname = nil;
-
- + initialize
- {
- if(!localHostname) {
- char DEOHostname[1024];
-
- gethostname(DEOHostname, 1024);
- localHostname = [[NSString alloc] initWithCString:DEOHostname];
- }
- return self;
- }
-
- + (NSString *)localHostname
- {
- return localHostname;
- }
-
- - initWithDatabaseChannel:(EODatabaseChannel *)aDatabaseChannel
- entity:(EOEntity *)anEntity
- {
- NSArray *objs;
- NSArray *keys;
-
- [super init];
-
- // localCenter is used for notification.
- localCenter = [[NSNotificationCenter alloc] init];
- entity = [anEntity retain];
- databaseChannel = [aDatabaseChannel retain];
-
- // Build the unique identifier for the DEONotificationCenter
- objs = [NSArray arrayWithObjects:
- localHostname,
- [NSString stringWithFormat:@"%d", getpid()],
- [anEntity name],
- [NSString stringWithFormat:@"%x", self],
- 0];
-
- keys = [NSArray arrayWithObjects:
- @"hostname",
- @"pid",
- @"entity",
- @"self",
- 0];
-
- localID = [[NSDictionary dictionaryWithObjects:objs forKeys:keys] retain];
-
- // Register self for notifications from monitor
- monitor = [[DEOServerMonitor serverMonitor] retain];
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(registerAgain:)
- notificationName:DEOServerReinitialize
- object:monitor];
-
- // We need to pass the server a pointer to our object, but it cannot
- // retain it, or a cycle will be created. Unfortunately, the server
- // MUST retain the object we pass it or the proxy on the server side
- // will be released. The solution is to pass the server an "holder"
- // object that it can retain (thus retaining the proxy) without
- // retaining us (thus avoiding a cycle). This holder must pass on
- // messages to our actual instance.
- container =
- [[DEONotificationCenterHolder alloc] initWithNonRetainedObject:self];
-
- [self registerAgain:nil];
-
- return self;
- }
-
- - (void)dealloc
- {
- [localCenter release];
- [entity release];
- [databaseChannel release];
- [localID release];
- NS_DURING
- [[monitor server] unregisterClient:(id <DEOClient>)container];
- NS_HANDLER
- NSLog(@"Failed to send remote method unregisterClient: to server.\n");
- NS_ENDHANDLER
- [container release];
- [monitor release];
- [super dealloc];
- return;
- }
-
- - (void)addObserver:observer
- selector:(SEL)selector
- notificationName:(NSString *)notificationName
- object:object
- {
- [localCenter addObserver:observer
- selector:selector
- notificationName:notificationName
- object:object];
- }
-
- - (void)removeObserver:observer
- notificationName:(NSString *)notificationName
- object:object;
- {
- [localCenter removeObserver:observer
- notificationName:notificationName
- object:object];
- }
-
- - (void)removeObserver:observer
- {
- [localCenter removeObserver:observer];
- }
-
- - (void)postNotificationName:(NSString *)notificationName object:object
- {
- [self postNotificationName:notificationName object:object userInfo:nil];
- }
-
- - (void)postNotificationName:(NSString *)name
- object:object
- userInfo:(NSDictionary *)userInfo;
- {
- NSMutableDictionary *info = [NSMutableDictionary dictionary];
- NSDictionary *primaryKey =
- [entity primaryKeyForRow:[[[databaseChannel databaseContext] database] snapshotForObject:object]];
-
- // Encodes the enterprise object in a dictionary with the primary key.
- [info setObject:primaryKey forKey:@"primaryKey"];
- [info setObject:name forKey:@"notificationName"];
- [info setObject:localID forKey:@"sender"];
-
- NS_DURING
- [[monitor server] dispatchInformation:info
- forKey:[entity name]
- userInfo:userInfo];
- NS_HANDLER
- NSLog(@"Failed to send remote method dispatchInformation:forKey:userInfo: to server.\n");
- NS_ENDHANDLER
- }
-
- @end
-
- @implementation DEONotificationCenter(Communication)
-
- - (oneway)dispatchInformation:(NSDictionary *)info
- forKey:(NSString *)key
- userInfo:(NSDictionary *)userInfo
- {
- // Decodes the enterprise object from information over the wire
- id database = [[databaseChannel databaseContext] database];
- id eoObject = [database objectForPrimaryKey:[info objectForKey:@"primaryKey"]
- entity:entity];
-
- if(!eoObject) {
- // Creates an EOFault if object does not exist yet
- [EOFault objectFaultWithPrimaryKey:[info objectForKey:@"primaryKey"]
- entity:entity
- databaseChannel:databaseChannel
- zone:NSDefaultMallocZone()];
- }
-
- [localCenter postNotification:
- [DEONotification notificationWithName:[info objectForKey:@"notificationName"]
- object:eoObject
- userInfo:userInfo
- isLocal:[[info objectForKey:@"sender"] isEqual:localID]]];
-
- return;
- }
-
- // Is called at init time or when the server has died.
- - (void)registerAgain:(NSNotification *)note
- {
- NS_DURING
- // Register as entity user in the distributed server
- [[monitor server] registerClient:(id <DEOClient>)container forKey:[entity name]];
- NS_HANDLER
- NSLog(@"Failed to send remote method registerClient:forKey: to server.\n");
- NS_ENDHANDLER
- }
-
- @end
-
- @implementation DEONotificationCenterHolder
-
- - initWithNonRetainedObject:(DEONotificationCenter *)aCenter
- {
- [super init];
- center = aCenter;
- return self;
- }
-
- - (oneway)dispatchInformation:(NSDictionary *)info
- forKey:(NSString *)key
- userInfo:(NSDictionary *)userInfo
- {
- [center dispatchInformation:info
- forKey:key
- userInfo:userInfo];
- }
- @end
-